home *** CD-ROM | disk | FTP | other *** search
- * ahdi.s
-
- *------------------------------------------------------------------------
- * :
- * ST SASI/AHDI hard disk driver :
- * Copyright 1985 Atari Corp. :
- * :
- *---- :
- * 31-Jan-1989 ml Cut this out from the real AHDI. :
- * Only low-level routines are kept. :
- * :
- *------------------------------------------------------------------------
-
- *----- System:
- flock equ $43e ; FIFO lock variable
- _hz_200 equ $4ba ; system 200hz timer
-
-
- *----- Hardware:
- wdc equ $ffff8604
- wdl equ $ffff8606
- wdcwdl equ wdc ; used for long writes
- xwdl equ wdl-wdc ; offset from wdc to wdl
-
- dmahi equ $ffff8609
- dmamid equ dmahi+2
- dmalow equ dmamid+2
- gpip equ $fffffa01
-
-
- *----- Tunable:
- ltimeout equ 450000 ; long-timeout (3 S)
- stimeout equ 15000 ; short-timeout (100 mS)
-
-
- *----- Declarations:
- tocount: dc.l 1 ; count down
-
-
- *+
- * LONG _qdone() - Wait for command byte handshake
- * LONG _fdone() - Wait for operation complete
- * Passed: nothing
- *
- * Returns: EQ: no timeout
- * MI: timeout condition
- *
- * Uses: D0
- *
- * each pass through the loop takes 6.75 uS
- *-
- _fdone: move.l #ltimeout,tocount
- bra qd1
-
- _qdone: move.l #stimeout,tocount
- qd1: subq.l #1,tocount ; drop timeout count
- bmi qdq ; (i give up, return NE)
- btst #5,gpip ; interrupt?
- bne qd1 ; (not yet)
-
- moveq #0,d0 ; return EQ (no timeout)
- rts
-
- qdq: moveq #-1,d0
- rts
-
-
- *+
- * WORD _endcmd()
- * Wait for end of SASI command
- * Passed: d0 value to be written to wdl
- *
- * Returns: EQ: success (error code in D0.W)
- * MI: timeout
- * NE: failure (SASI error code in D0.W)
- *
- * Uses: d0,d1
- *-
- _endcmd: move d0,d1 ; preserve wdl value
-
- bsr _fdone ; wait for operation complete
- bmi endce ; (timed-out, so complain)
-
- move.w d1,wdl
- nop
- move.w wdc,d0 ; get the result
- and.w #$00ff,d0 ; (clean it up), if non-zero should
-
- endce: rts ; do a ReadSense command to learn more
-
-
-
- *-
- * _hread(sectno, count, buf, dev)
- * LONG sectno; 4(sp)
- * WORD count; 8(sp)
- * LONG buf; $a(sp) $b=high, $c=mid, $d=low
- * WORD dev; $e(sp)
- *
- * Returns: -1 on timeout
- * 0 on success
- * nonzero on error
- *
- *-
- .globl _hread
- _hread:
- movea.l #wdc,a0 ; pointer to DMA chip
- st flock ; lock FIFO
-
- move #$88,xwdl(a0)
- clr.l d0
- move.w $0e(sp),d0 ; get unit number
- lsl.w #5,d0
- swap d0
- ori.l #$0008008a,d0 ; 08 wdc, 8a wdl
- move.l d0,(a0) ; wdcwdl
-
- move.l $a(sp),-(sp) ; set DMA address
- bsr _setdma
- addq #4,sp
-
- bsr _setss ; set sector and size
- bmi _hto
-
- move.w #$190,xwdl(a0)
- nop
- move.w #$90,xwdl(a0)
- nop
- move.w 8(sp),(a0) ;wdc ; write sector count to DMA chip
- nop
- move.w #$8a,xwdl(a0)
- nop
- move.l #$00000000,(a0) ; wdcwdl; control byte 0 wdc 0 wdl
-
- move.w #$8a,d0
- bsr _endcmd
- hrx: bra _hdone ; cleanup after IRQ
-
-
- *-
- * _hwrite(sectno, count, buf, dev)
- * LONG sectno; 4(sp)
- * WORD count; 8(sp)
- * LONG buf; $a(sp) $b=high, $c=mid, $d=low
- * WORD dev; $e(sp)
- *
- *-
- .globl _hwrite
- _hwrite:
- movea.l #wdc,a0 ; pointer to DMA chip
- st flock ; lock FIFO
-
- move.l $a(sp),-(sp) ; set DMA address
- bsr _setdma
- addq #4,sp
-
- move.w #$88,xwdl(a0)
- clr.l d0
- move.w $0e(sp),d0 ; get unit number
- lsl.w #5,d0
- swap d0
- ori.l #$000a008a,d0 ; 0a wdc 8a wdl
- move.l d0,(a0) ; wdcwdl
-
- bsr _setss
- bmi _hto
-
- move.w #$90,xwdl(a0)
- nop
- move.w #$190,xwdl(a0)
- nop
- move.w 8(sp),(a0) ;wdc ; sector count for DMA chip's benefit
- nop
- move.w #$18a,xwdl(a0)
- nop
- move.l #$00000100,(a0) ; wdcwdl
-
- move.w #$18a,d0
- bsr _endcmd
-
- hwx: bra _hdone ; cleanup after IRQ
-
-
- *+
- * void _setdma(addr)
- * LONG addr;
- *-
- _setdma:
- move.b 7(sp),dmalow
- move.b 6(sp),dmamid
- move.b 5(sp),dmahi
- rts
-
- *+
- * WORD _setss -- set sector number and number of sectors
- *-
- _setss: move.w #$8a,xwdl(a0)
-
- bsr _qdone ; wait for controller to take command
- bmi setsse
-
- move.b 9(sp),d0 ; construct sector#
- swap d0
- move.w #$008a,d0
- move.l d0,(a0) ; wdcwdl ; write MSB sector# + devno
- bsr _qdone
- bmi setsse
-
- move.b 10(sp),d0 ; write MidSB sector#
- swap d0
- move.w #$008a,d0
- move.l d0,(a0) ; wdcwdl
- bsr _qdone
- bmi setsse
-
- move.b 11(sp),d0 ; write LSB sector#
- swap d0
- move.w #$008a,d0
- move.l d0,(a0) ; wdcwdl
- bsr _qdone
- bmi setsse
-
- move.w 12(sp),d0 ; write sector count
- swap d0
- move.w #$008a,d0
- move.l d0,(a0) ; wdcwdl
- bsr _qdone
-
- setsse: rts
-
- _hto: moveq #-1,d0 ; indicate timeout
- _hdone: move.w #$80,wdl ; Landon's code seems to presume we
- nop ; put this back to $80
- tst.w wdc
- clr flock ; NOW, signal that we are done
- rts
-
-
- * page
- *+
- * _doformat - format hard disk
- *
- * Synopsis: LONG _doformat(dev, interlv)
- * WORD dev; 4(sp).W
- * WORD interlv; 6(sp).W
- *
- *-
- acfmt: dc.b 4 ; format command + devno (upper 3 bits)
- dc.b 0 ; (unused)
- dc.b 0 ; (unused) data pattern
- ac_in: dc.b 0,0 ; interleave factor MSB, LSB
- dc.b 0 ; reserved
- .even
-
- .globl _doformat
- _doformat:
- move.w 4(sp),d0 ; set dev#
- lsl.b #5,d0 ; up 5 bits, fill in 0s
- or.b #4,d0 ; OR-in with FORMAT command
- move.b d0,acfmt ; stuff into command frame
- move.b 6(sp),ac_in ; set interleave
- move.b 7(sp),ac_in+1
-
- lea acfmt(pc),a0 ; pick up pointer to the command block
- clr.w d0
- st flock ; lock FIFO
- move.w #$88,wdl
- move.b (a0)+,d0 ; get the command byte
- swap d0
- move.w #$8a,d0
- move.l d0,wdc ; byte wdc 8a wdl
-
- moveq #(5-1),d1 ; write remaining 5 bytes of command
- fmt1: bsr _qdone
- bmi _hto
- move.b (a0)+,d0 ; next byte of command
- swap d0
- move.w #$8a,d0
- move.l d0,wdcwdl
- dbra d1,fmt1
-
- fmt2: btst #5,gpip ; wait (forever) for completion
- bne fmt2
- move.w wdc,d0 ; get the status
- andi.w #$00FF,d0 ; only low byte is significant
- bra _hdone ; cleanup after IRQ
-
-
- *+
- * _mode_set - set hard disk format parameters
- *
- * Synopsis: LONG _mode_set(dev, len, parms)
- * WORD dev; 4(sp).W
- * WORD len; 6(sp).W
- * char *parms; 8(sp).L
- *
- *-
- .globl _mode_set
- _mode_set:
- st flock ; lock FIFO
- move.l 8(sp),-(sp) ; -> parameter block address
- bsr _setdma ; set DMA there
- addq #4,sp
-
- * write command and dev#
- move.w #$88,wdl
- move.w 4(sp),d0 ; d0 = (dev << 5) << 16
- lsl.b #5,d0
- swap d0 ; in upper word
- or.l #$0015008a,d0 ; write dev# + ModeSelect + FIFO bits
- move.l d0,wdcwdl ; mdsel+dev wdc 8a wdl (byte 0)
- bsr _qdone
- bmi wdx
-
- move.l #$0000008a,wdcwdl ; byte 1
- bsr _qdone
- bmi wdx
-
- move.l #$0000008a,wdcwdl ; byte 2
- bsr _qdone
- bmi wdx
-
- move.l #$0000008a,wdcwdl ; byte 3
- bsr _qdone
- bmi wdx
-
- move.w 6(sp),d0 ; # bytes of parameter
- swap d0 ; in upper word
- or.l #$0000008a,d0
- move.l d0,wdcwdl ; byte 4
- bsr _qdone
- bmi wdx
-
- move.w #$90,wdl ; reset the DMA chip
- nop
- move.w #$190,wdl
- nop
- move.w #$01,wdc ; 1 sector of DMA (actually less)
- nop
- move.w #$18a,wdl
- nop
- move.l #$00000100,wdcwdl ; byte 5 (control byte)
- move.w #$18a,d0 ; wdl value
- bsr _endcmd ; wait for command completion
- wdx: bra _hdone
-
-
- * page
- *+
- * _md_sense - get hard disk format parameters
- *
- * Synopsis: LONG _md_sense(dev, parms)
- * WORD dev; 4(sp).W
- * char *parms; 6(sp).L
- *
- *-
- .globl _md_sense
- _md_sense:
- st flock ; lock FIFO
- move.l 6(sp),-(sp) ; -> parameter block address
- bsr _setdma ; set DMA there
- addq #4,sp
-
- * write command and dev#
- move.w #$88,wdl
- move.w 4(sp),d0 ; d0 = (dev << 5) << 16
- lsl.b #5,d0
- swap d0 ; in upper word
- or.l #$001a008a,d0 ; write dev# + ModeSense + FIFO bits
- move.l d0,wdcwdl ; mdsense+dev wdc 8a wdl (byte 0)
- bsr _qdone
- bmi wdx1
-
- move.l #$0000008a,wdcwdl ; byte 1
- bsr _qdone
- bmi wdx1
-
- move.l #$0000008a,wdcwdl ; byte 2
- bsr _qdone
- bmi wdx1
-
- move.l #$0000008a,wdcwdl ; byte 3
- bsr _qdone
- bmi wdx1
-
- move.l #$0016008a,wdcwdl ; 22 bytes of parameters (byte 4)
- bsr _qdone
- bmi wdx1
-
- move.w #$190,wdl ; reset the DMA chip
- nop
- move.w #$90,wdl
- nop
- move.w #$01,wdc ; 1 sector of DMA (actually less)
- nop
- move.w #$8a,wdl
- nop
- move.l #0,wdcwdl ; byte 5 (control byte)
- move.w #$8a,d0 ; wdl value
- bsr _endcmd ; wait for command completion
- wdx1: bra _hdone
-
-
- * page
- *+
- * _rq_sense - get sense data from target
- *
- * Synopsis: LONG _rq_sense(dev, data)
- * WORD dev; 4(sp).W
- * char data[]; 6(sp).L
- *
- *-
- .globl _rq_sense
- _rq_sense:
- st flock ; lock FIFO
- move.l 6(sp),-(sp) ; -> sense data buffer address
- bsr _setdma ; set DMA there
- addq #4,sp
-
- move.w #$190,wdl ; reset the DMA chip
- nop
- move.w #$90,wdl
- nop
- move.w #$01,wdc ; 1 sector of DMA (actually less)
- nop
-
- * write command and dev#
- * have to do this 4 times to have controller write it into RAM
- move #3,d2 ; (count = 4)
- loop4x:
- move.w #$88,wdl
- move.w 4(sp),d0 ; d0 = (dev << 5) << 16
- lsl.b #5,d0
- swap d0 ; in upper word
- or.l #$0003008a,d0 ; write dev#+Request Sense+FIFO bits
- move.l d0,wdcwdl ; rqsense+dev wdc 8a wdl (byte 0)
- bsr _qdone
- bmi wdq1
-
- move.l #$0000008a,wdcwdl ; byte 1
- bsr _qdone
- bmi wdq1
-
- move.l #$0000008a,wdcwdl ; byte 2
- bsr _qdone
- bmi wdq1
-
- move.l #$0000008a,wdcwdl ; byte 3
- bsr _qdone
- bmi wdq1
-
- move.l #$0000008a,wdcwdl ; byte 4
- bsr _qdone
- bmi wdq1
-
- move.w #$8a,wdl
- nop
- move.l #0,wdcwdl ; byte 5 (control byte)
- move.w #$8a,d0 ; wdl value
- bsr _endcmd ; wait for command completion
- bmi wdq1
-
- move.l _hz_200,d1
- addq.l #2,d1
- wait:
- cmp.l _hz_200,d1 ; delay 2 ticks between
- bcc wait ; driver calls
- dbra d2,loop4x ; go back until done 4 times
-
- wdq1: bra _hdone
-
-
- * page
- *+
- * _tstunt - test unit ready
- *
- * Synopsis: LONG _tstunt(dev)
- * WORD dev; 4(sp).W
- *
- *-
- .globl _tstunt
- _tstunt:
- move.w 4(sp),d0 ; set dev#
- lsl.b #5,d0 ; up 5 bits, fill in 0s
-
- st flock ; lock FIFO
- move.w #$88,wdl
- swap d0
- move.w #$8a,d0
- move.l d0,wdc ; byte wdc 8a wdl
-
- moveq #(5-1),d1 ; write remaining 5 bytes of command
- tu1: bsr _qdone
- bmi _hto
- move.l #$0000008a,wdcwdl ; next byte of command
- dbra d1,tu1
-
- move.w #$8a,d0
- bsr _endcmd
- bra _hdone ; cleanup after IRQ
-
-